﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Collections;
using System.Runtime.CompilerServices;
using NLog;

namespace TwitterFx
{
    class TwitterClient
    {
        public string UserName { get; set; }
        public string Password { get; set; }
		
		public const string USER_AGENT = "TeetsFX";

		private static Logger log = LogManager.GetCurrentClassLogger();
		private TwitterFxConfig config = TwitterFxConfig.GetTwitterFxConfig();

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void PopulateEntries(Gtk.ListStore entryListStore)
		{
            log.Debug("Fetching entries");
			
			string json = FetchURL("http://api.twitter.com/1/statuses/home_timeline.json?count=20");
			
			log.Debug("JSON fetched");
						
			IList rawEntries = (IList) JSON.JsonDecode(json);
			
			log.Debug("JSON decoded");
			
			entryListStore.Clear();
			
			Dictionary<string, string> icons = new Dictionary<string, string>();

            foreach (Object o in rawEntries)
            {
                log.Debug("Iterating");
				
				Hashtable h = o as Hashtable;
                Hashtable u = h["user"] as Hashtable;

                Entry entry = new Tweet();
				
				string screenName = (string) u["screen_name"];
                entry.User = screenName;
                entry.UserUrl = (string) u["url"];
				
				string iconUrl = (string)u["profile_image_url"];
				if (iconUrl != null)
				{
					if (!icons.ContainsKey(screenName)) {
						string path = Path.Combine(config.iconsPath, screenName + iconUrl.Substring(iconUrl.LastIndexOf(".")));
						CacheFile(iconUrl, path);
						entry.Icon = path;
						icons.Add(screenName, path);
					} else {
						entry.Icon = icons[screenName];
					}
				}

				entry.Text = (string)h["text"];
                entry.CreatedAt = (string)h["created_at"];

                entryListStore.AppendValues(entry);
            }
		}
		
		private void CacheFile(string url, string path)
		{
			//TODO: check timestamp
			if (!File.Exists(path))
			{
				log.Debug("Saving file");
				SaveUrl(url, path);
				log.Debug("file saved");
			}
			else
			{
				log.Debug("File exists");
			}
		}
		
		public void Post(string text) {
			PostData("http://api.twitter.com/1/statuses/update.json", "status=" + text);
		}

		private void SaveUrl(string url, string path)
		{
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
            request.Timeout = 500000;
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = USER_AGENT;

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            Stream resStream = response.GetResponseStream();
			long len = response.ContentLength;
			
			FileStream fs = File.OpenWrite(path);
			for (int i = 0; i < len; i++)
			{
				fs.WriteByte((byte) resStream.ReadByte());
			}
			fs.Close();
			resStream.Close();
		}
		
        private string FetchURL(string url)
        {
			ICredentials credentials = new NetworkCredential(UserName, Password);
			
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
            request.Timeout = 500000;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = USER_AGENT;
            request.Credentials = credentials;

            //ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
            //ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; };

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
			log.Debug("Response received");

            Stream resStream = response.GetResponseStream();
            StreamReader sr = new StreamReader(resStream);
            string result = sr.ReadToEnd();
            sr.Close();
            return result;
        }
		
		private string PostData(string url, string data)
        {
            string user = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(UserName + ":" + Password));
			byte[] bytes = Encoding.ASCII.GetBytes(data);
			
			HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
            request.Timeout = 500000;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = USER_AGENT;
			
			request.ServicePoint.Expect100Continue = false;
			request.Headers.Add("Authorization", "Basic " + user);
			request.Headers.Add("X-Twitter-Client", "TweetsFX");
			request.Headers.Add("X-Twitter-Client-Version", "1.0");
			request.Headers.Add("X-Twitter-Client-URL", "http://netdukes.com");
			
            request.ContentLength = bytes.Length;
			Stream reqStream = request.GetRequestStream();
			reqStream.Write(bytes, 0, bytes.Length);
			reqStream.Close();
			
            //ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
            //ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; };

            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            Stream resStream = response.GetResponseStream();
            StreamReader sr = new StreamReader(resStream);
            string result = sr.ReadToEnd();
            sr.Close();
            return result;
        }

    }
}
